//导入node的express框架
const express = require('express')
const expressWs = require('express-ws')
//导入cors中间件
const cors = require('cors')
//导入用户路由模块
const userRouter = require('./router/user')
//导入获取用户信息路由模块
const infoRouter = require('./router/info')
//导入webSocket路由模块
const wsRouter = require('./router/ws')
//导入静态文件资源的路由模块
const staticRouter = require('./router/static')
//导入解析token的包
const expressJWT = require('express-jwt')
//导入全局配置文件
const config = require('./config')
//导入处理客户端数据的包
const bodyParser = require('body-parser')
const multiparty = require('connect-multiparty')
//导入生成媒体文件夹的方法
const fileUtils = require('./utils/file')
//导入路径定义方法
const path = require('path')

//创建服务器实例对象
const app = express()
//通过express-ws扩展 app 实例
expressWs(app)

//处理 x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }))
//处理 multipart/form-data
app.use(multiparty())
//处理 application/json
app.use(bodyParser.json({ limit: '50mb' }))

//配置cors中间件
app.use(cors())
//配置解析表单数据的中间件,只能解析application/x-www-form-urlencoded格式的表单数据
app.use(express.urlencoded({ extended: false }))
// 响应数据的中间件
app.use(function (req, res, next) {
    //code=200为成功,code=201为失败!默认将code的值设置为201，方便处理失败的情况
    res.cc = function (err, code = 201) {
        res.send({
            //状态
            code,
            //状态描述，判断err是错误对象还是字符串
            message: err instanceof Error ? err.message : err,
        })
    }
    next()
})
//配置解析token的中间件
app.use(
    expressJWT({ secret: config.jwtSecretKey }).unless({
        path: [
            /^\/api\/user\/login/, // 匹配 /api/user/login
            /^\/api\/user\/register/, // 匹配 /api/user/register
            /^\/api\/user\/logout/, // 匹配 /api/user/logout
            /^\/api\/ws(\/.*)?$/, // 匹配websocket及其子路径
            /^\/chatAppServer(\/.*)?$/, // 匹配文件资源路径
        ],
    }),
)
//将chatApp文件夹公开为静态资源
app.use('/chatAppServer', express.static(path.join('D:/Documents/', 'chatAppServer')))
//确保服务器有保存媒体文件的文件夹
fileUtils.ensureDirectoriesExist(path.join('D:/Documents/', 'chatAppServer'), config.subDirectories)

//使用用户路由模块
app.use('/api', userRouter)
//使用获取用户信息路由模块
app.use('/api', infoRouter)
//发送消息的ws路由模块
app.use('/api', wsRouter)
//获取chatApp文件夹(服务器)内容的路由模块
app.use('/api', staticRouter)

//定义错误级别的中间件
app.use(function (err, req, res, next) {
    //身份认证失败后的错误
    if (err.name === 'UnauthorizedError') {
        return res.cc('身份认证失败!')
    }
    //未知的错误
    return res.cc(err)
})

//启动服务器
app.listen(config.port, '0.0.0.0', () => {
    console.log(`api server running at ${config.host}:${config.port}`)
})
